/*
	i8250.h
	
	Defines UART 16550(maybe) constants and calls
	http://www.lammertbies.nl/comm/info/serial-uart.html
	
	Meng Sun(c) leon.meng.sun@gmail.com
	Source code released under LGPLv3
	https://www.gnu.org/licenses/lgpl-3.0.txt
*/

#ifndef ISAMIPS_QEMU_SERIAL
#define ISAMIPS_QEMU_SERIAL

#include "board.h"

#define SERIAL_BASE ((unsigned char*)(ISA_IO_BASE + 0x3f8))

#define RBR *(SERIAL_BASE)
#define THR *(SERIAL_BASE)
#define DLL *(SERIAL_BASE)
#define DLM *(SERIAL_BASE + 1)
#define IER *(SERIAL_BASE + 1)
#define IIR *(SERIAL_BASE + 2)
#define FCR *(SERIAL_BASE + 2)
#define LCR *(SERIAL_BASE + 3)
#define MCR *(SERIAL_BASE + 4)
#define LSR *(SERIAL_BASE + 5)
#define MSR *(SERIAL_BASE + 6)
#define SCR *(SERIAL_BASE + 7)

#define I8250BUFFERSIZE 128

enum _ansiesc_gmode_txt{
	ANSIESC_GMODE_TXT_ALLATTOFF = '0',
	ANSIESC_GMODE_TXT_BOLD = '1',
	ANSIESC_GMODE_TXT_UNDERSCORE = '4',
	ANSIESC_GMODE_TXT_BLINK = '5',
	ANSIESC_GMODE_TXT_REVERSEVIDEO = '7',
	ANSIESC_GMODE_TXT_CONCEALED = '8'
};

typedef enum _ansiesc_gmode_txt ansiesc_gmode_txt;

enum _ansiesc_gmode_fgc{
	ANSIESC_GMODE_FGC_BLACK = '0',
	ANSIESC_GMODE_FGC_RED = '1',
	ANSIESC_GMODE_FGC_GREEN = '2',
	ANSIESC_GMODE_FGC_YELLOW = '3',
	ANSIESC_GMODE_FGC_BLUE = '4',
	ANSIESC_GMODE_FGC_MAGENTA = '5',
	ANSIESC_GMODE_FGC_CYAN = '6',
	ANSIESC_GMODE_FGC_WHITE = '7'
};

typedef enum _ansiesc_gmode_fgc ansiesc_gmode_fgc;

enum _ansiesc_gmode_bgc{
	ANSIESC_GMODE_BGC_BLACK = '0',
	ANSIESC_GMODE_BGC_RED = '1',
	ANSIESC_GMODE_BGC_GREEN = '2',
	ANSIESC_GMODE_BGC_YELLOW = '3',
	ANSIESC_GMODE_BGC_BLUE = '4',
	ANSIESC_GMODE_BGC_MAGENTA = '5',
	ANSIESC_GMODE_BGC_CYAN = '6',
	ANSIESC_GMODE_BGC_WHITE = '7'
};

typedef enum _ansiesc_gmode_bgc ansiesc_gmode_bgc;

enum _i8250PrintfStateMachine{
	i8250PRINTFSTATETEXT,
	i8250PRINTFSTATEFORMAT,
	i8250PRINTFSTATEESCAPE
};

typedef enum _i8250PrintfStateMachine i8250PrintfStateMachine;

#define ERRORLOG(info, ...) \
		i8250SetGraphicsModeError(); \
		i8250Printf("[ERROR: %8x : %8x] - " info "\n", getEpocCounterHi(), getEpocCounterLo(), ##__VA_ARGS__); \
		i8250SetGraphicsModePlain();

#define WARNINGLOG(info, ...) \
		i8250SetGraphicsModeWarning(); \
		i8250Printf("[WARN: %8x : %8x] - " info "\n", getEpocCounterHi(), getEpocCounterLo(), ##__VA_ARGS__); \
		i8250SetGraphicsModePlain();

#define INFORMATIONLOG(info, ...) \
		i8250SetGraphicsModeInformation(); \
		i8250Printf("[INFO: %8x : %8x] - " info "\n", getEpocCounterHi(), getEpocCounterLo(), ##__VA_ARGS__); \
		i8250SetGraphicsModePlain();

void i8250PutStr(unsigned char*);

void i8250SetGraphicsMode(ansiesc_gmode_txt, ansiesc_gmode_fgc, ansiesc_gmode_bgc);

void i8250SetGraphicsModeInformation(void);

void i8250SetGraphicsModeWarning(void);

void i8250SetGraphicsModeError(void);

void i8250SetGraphicsModePlain(void);

void i8250Init();

void i8250PutChar(unsigned char);

void i8250Printf(unsigned char*, ...);

#endif

